package storeSorting

import (
	"context"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"github.com/kuangshp/go-utils/k"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"insighttracking/apps/admin/auth"
	"insighttracking/common/enum"
	"insighttracking/common/utils"
	"insighttracking/query/bo"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"insighttracking/query/service"
	"net/http"

	"insighttracking/apps/admin/internal/svc"
	"insighttracking/apps/admin/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
	"os"
)

type CreateStoreSortingApiLogic struct {
	logx.Logger
	ctx     context.Context
	svcCtx  *svc.ServiceContext
	Request *http.Request
}

func NewCreateStoreSortingApiLogic(ctx context.Context, svcCtx *svc.ServiceContext, request *http.Request) *CreateStoreSortingApiLogic {
	hostname, _ := os.Hostname()
	return &CreateStoreSortingApiLogic{
		Logger: logx.WithContext(ctx).WithCallerSkip(0).WithFields(
			logx.Field("Log_UUID", uuid.New().String()),
			logx.Field("hostname", hostname)),
		ctx:     ctx,
		svcCtx:  svcCtx,
		Request: request,
	}
}

func (l *CreateStoreSortingApiLogic) CreateStoreSortingApi(req *types.CreateStoreSortingReq) (resp string, err error) {
	// todo: add your logic here and delete this line
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return "", err
	}
	ordersDetailIdList := k.Map(req.DataList, func(item types.StoreSortingDetailReq, index int) int64 {
		return item.OrdersDetailId
	})
	detailEntities, err := service.OrdersDetailService.GetByIdListApi(l.ctx, ordersDetailIdList)
	if err != nil || len(detailEntities) == 0 {
		return "", errors.New("传递的订单号错误")
	}
	detailMap := k.ToMap(detailEntities, func(item *bo.OrderDetailBo) (int64, *bo.OrderDetailBo) {
		return item.ID, item
	})
	var totalAmount = decimal.Zero
	var totalCount = decimal.Zero
	for _, item := range req.DataList {
		outboundCount, _ := decimal.NewFromString(item.OutboundCount)
		totalCount = totalCount.Add(outboundCount)
		spuItem := detailMap[item.OrdersDetailId]
		totalAmount = totalAmount.Add(spuItem.SnapshotPrice.Mul(outboundCount))
	}
	tx := dao.Use(l.svcCtx.MysqlDb).Begin()
	storeSortingEntity, err := service.StoreSortingService.GetStoreSortingByOrderIdApi(l.ctx, req.OrdersID)
	var storeSortingID int64
	if errors.Is(err, gorm.ErrRecordNotFound) {
		storeSortingData := &model.StoreSortingEntity{
			OrderNo:      utils.GenerateTodayOrderNo(l.svcCtx.RedisDb, "FJCK"), // 订单流水号
			EnterpriseID: accountInfo.EnterpriseId,                             // 关联到enterprise表主键id
			CustomerID:   req.CustomerID,                                       // 客户id,关联到enterprise_customer表主键id
			TotalAmount:  totalAmount,                                          // 订单金额
			TotalCount:   totalCount,                                           // 订单商品数量
			WarehouseID:  req.WarehouseID,                                      // 出库仓库,关联到warehouse表主键id
			OrdersID:     req.OrdersID,                                         // 关联到订单表id,orders表主键id
			OperateName:  accountInfo.PersonName,                               // 制单员
			OperateID:    accountInfo.PersonId,                                 // 制单员id,关联到员工表
			Remark:       req.Remark,                                           // 备注
		}
		if err = service.StoreSortingService.CreateApi(l.ctx, tx, storeSortingData); err != nil {
			if err = tx.Rollback(); err != nil {
				return "", err
			}
			return "", err
		}
		storeSortingID = storeSortingData.ID
	} else {
		storeSortingID = storeSortingEntity.ID
		if err = service.StoreSortingService.ModifyByIdApi(l.ctx, tx, storeSortingEntity.ID, storeSortingEntity.TotalCount.Add(totalCount), storeSortingEntity.TotalAmount.Add(totalAmount)); err != nil {
			if err := tx.Rollback(); err != nil {
				return "", err
			}
			return "", err
		}
	}

	// 创建明细
	var storeSortingDetail = make([]*model.StoreSortingDetailEntity, 0)
	for _, item := range req.DataList {
		spuItem, isOk := detailMap[item.OrdersDetailId]
		if !isOk {
			continue
		}
		outboundCount, _ := decimal.NewFromString(item.OutboundCount)
		lossCount := outboundCount.Mul(spuItem.SnapshotLossRate)
		// 判断库存是否足够
		spuInventory := service.SpuInventoryService.GetSpuInventoryApi(l.ctx, accountInfo.EnterpriseId, spuItem.SpuID, req.WarehouseID)
		if spuInventory.LessThan(outboundCount.Add(lossCount)) {
			if err = tx.Rollback(); err != nil {
				return "", err
			}
			return "", errors.New("当前商品库存数量少于出库数量,无法出库")
		}
		storeSortingDetail = append(storeSortingDetail, &model.StoreSortingDetailEntity{
			StoreSortingID:          storeSortingID,                  // 分拣单store_sorting主键id
			OrdersDetailID:          item.OrdersDetailId,             // 主键id
			SpuID:                   spuItem.SpuID,                   // 商品,关联到spu表主键id
			SnapshotSpuName:         spuItem.SnapshotName,            // 快照商品名称
			SnapshotProductImageURL: spuItem.SnapshotProductImageURL, // 快照产品图片
			SnapshotSpuType:         spuItem.SnapshotSpuType,         // 快照商品类型,0表示基础商品,1表示加工商品
			SnapshotUnit:            spuItem.SnapshotUnit,            // 快照单位
			SnapshotCategoryID:      spuItem.SnapshotCategoryID,      // 快照分类id
			SnapshotCategory:        spuItem.SnapshotCategory,        // 快照分类
			LossRate:                spuItem.SnapshotLossRate,        // 快照损耗率
			OrdersCount:             spuItem.SpuCount,                // 下单数量
			SnapshotPrice:           spuItem.SnapshotPrice,           // 快照商品单价
			OutboundCount:           outboundCount,                   // 出库数量
			LossCount:               lossCount,                       // 出库损耗
			OperateName:             accountInfo.PersonName,          // 出库员
			OperateID:               accountInfo.PersonId,            // 出库员id,关联到员工表
			Remark:                  item.Remark,                     // 备注
			UUID:                    utils.UuIdV4(),
		})
	}
	if err = service.StoreSortingDetailService.CreateBatchApi(l.ctx, tx, storeSortingDetail); err != nil {
		if err = tx.Rollback(); err != nil {
			return "", err
		}
		return "", err
	}
	// 修改订单详情状态
	if err = service.OrdersDetailService.ModifyStatusByIdListApi(l.ctx, tx, ordersDetailIdList, enum.OrdersSortingFinishEnum); err != nil {
		return "", err
	}

	ordersDetailEntities, err := service.OrdersDetailService.GetByOrderIdListApi(l.ctx, []int64{req.OrdersID})
	if err == nil && len(ordersDetailEntities) > 0 {
		if k.Every(ordersDetailEntities, func(item *model.OrdersDetailEntity, index int) bool {
			return item.Status == enum.OrdersSortingFinishEnum
		}) {
			// 等全部订单详情都分拣完成订单才改分拣
			if err = service.OrdersService.ModifyStatusByIdApi(l.ctx, nil, []int64{req.OrdersID}, enum.OrdersSortingFinishEnum); err != nil {
				l.Errorf("修改状态失败:[%v]", err)
			}
		} else if err = service.OrdersService.ModifyStatusByIdApi(l.ctx, nil, []int64{req.OrdersID}, enum.OrdersSortingProgressEnum); err != nil {
			l.Errorf("修改状态失败:[%v]", err)
		}
	}
	if err = tx.Commit(); err != nil {
		fmt.Println(err, "错误了11")
		return "", errors.New("分拣失败")
	}
	// 修改订单状态
	return "操作成功", nil
}
